<template>
  <div class="app-container" v-loading="loading" element-loading-text="加载中">
    <el-card shadow="never">
      <div class="flex justify-between">
        <div v-if="hasAnthority('fileItem.add')">
          <el-button type="primary" :icon="CirclePlus" @click="addDialogVisible = true">新增必要文件</el-button>
        </div>
        <div>
          <el-tooltip content="刷新表格">
            <el-button type="primary" :icon="RefreshRight" circle @click="handleRefresh" />
          </el-tooltip>
        </div>
      </div>
      <div class="mt-5">
        <el-table :data="FileData">
          <el-table-column show-overflow-tooltip prop="name" label="文件名" align="center" />
          <el-table-column prop="type" label="文件类型" align="center" />
          <el-table-column fixed="right" label="操作" align="center">
            <template #default="scope">
              <el-button
                v-if="hasAnthority('fileItem.update')"
                type="primary"
                text
                bg
                size="small"
                @click="handleUpdate(scope.row)"
                >修改</el-button
              >
              <el-button
                v-if="hasAnthority('fileItem.delete')"
                type="danger"
                text
                bg
                size="small"
                @click="handleDelete(scope.row)"
                >删除</el-button
              >
              <el-button
                v-if="hasAnthority('fileItem.grant')"
                type="success"
                text
                bg
                size="small"
                @click="handleAllocation(scope.row)"
                >分配</el-button
              >
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div class="mt-5">
        <el-pagination
          hide-on-single-page
          background
          :layout="paginationData.layout"
          :page-sizes="paginationData.pageSizes"
          :total="paginationData.total"
          :page-size="paginationData.pageSize"
          :currentPage="paginationData.currentPage"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </el-card>

    <!-- 新增/修改 -->
    <el-dialog
      v-model="addDialogVisible"
      :title="currentUpdateId === undefined ? '新增必要文件' : '修改必要文件'"
      @close="resetForm"
      width="50%"
    >
      <el-form ref="addFormRef" :model="addFormData" :rules="addFormRules" label-width="110px" label-position="left">
        <el-form-item prop="name" label="文件名">
          <el-input v-model="addFormData.name" placeholder="请输入" />
        </el-form-item>
        <el-form-item prop="type" label="文件类型">
          <el-select v-model="addFormData.type" placeholder="请选择文件类型">
            <el-option v-for="item in necessaryFileType" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="文件模版">
          <el-upload
            action="#"
            :on-exceed="handleExceed"
            :limit="1"
            :http-request="requestUpload"
            :before-upload="beforeUpload"
            ref="uploadRef"
            v-model:file-list="fileList"
            :accept="addFormData.type"
          >
            <el-button>
              上传
              <el-icon class="el-icon--right"><Upload /></el-icon>
            </el-button>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="addDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleCreate">确认</el-button>
      </template>
    </el-dialog>

    <el-dialog
      destroy-on-close
      v-model="treeDialogVisible"
      title="请勾选需要上传该必要资料的办学单位"
      @closed="
        () => {
          TreeData = []
          filterText = ''
        }
      "
      width="50%"
    >
      <div class="tree-box p-2" style="max-height: 400px; overflow-y: auto; min-height: 200px">
        <div class="flex items-center">
          <span class="w-16">关键字</span>
          <el-input v-model="filterText" placeholder="搜索" />
        </div>

        <el-tree
          class="mt-5"
          check-on-click-node
          ref="treeRef"
          node-key="id"
          highlight-current
          :default-checked-keys="defaultCheckedKeys"
          :props="props"
          :data="TreeData"
          show-checkbox
          @check="handleCheckChange"
          :filter-node-method="filterNode"
        />
      </div>

      <template #footer>
        <el-button @click="treeDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleConfirmTree">确认</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { CirclePlus, RefreshRight } from "@element-plus/icons-vue"
import { usePagination } from "@/hooks/usePagination"
import {
  addFileDataApi,
  deleteFileDataApi,
  getFileDataApi,
  getGrantListApi,
  updateFileDataApi,
  updateGrantApi,
  uploadTemplateApi
} from "@/api/necessary"
import { reactive, ref, watch } from "vue"
import {
  IAddFileRequestData,
  IGetFileResponseData,
  IGetGrantListResponseData,
  IUpdateGrantRequestData
} from "@/api/necessary/types/necessary"
import {
  ElMessageBox,
  ElTree,
  FormInstance,
  FormRules,
  UploadInstance,
  UploadProps,
  UploadRawFile,
  UploadUserFile,
  genFileId
} from "element-plus"
import { getCheckedKeys, showPromptMessage } from "@/utils"
import { necessaryFileType } from "@/config/data"
import { hasAnthority } from "@/utils"

const { paginationData, handleCurrentChange, handleSizeChange } = usePagination()

const searchData = ref({
  name: ""
})
const filterText = ref("")
const loading = ref(false)
const FileData = ref<IGetFileResponseData[]>([])
const getFileData = () => {
  loading.value = true
  getFileDataApi({ page: paginationData.currentPage, size: paginationData.pageSize, ...searchData.value })
    .then((res) => {
      FileData.value = res.data.list
    })
    .catch(() => {
      FileData.value = []
    })
    .finally(() => {
      loading.value = false
    })
}
getFileData()
const handleUpdate = (row: IGetFileResponseData) => {
  currentUpdateId.value = row.id
  addDialogVisible.value = true
  addFormData.type = row.type
  addFormData.name = row.name
}
const handleDelete = (row: IGetFileResponseData) => {
  ElMessageBox.confirm(`正在删除必要文件：${row.name}，确认删除？`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(() => {
    deleteFileDataApi(row.id).then(() => {
      showPromptMessage("success", "删除成功")
      getFileData()
    })
  })
}

const addFormRules: FormRules = reactive({
  name: [{ required: true, trigger: "blur", message: "请输入文件名称" }]
})
const addFormRef = ref<FormInstance | null>(null)
const addFormData = reactive<IAddFileRequestData>({
  name: "",
  type: "不做限定"
})
const addDialogVisible = ref(false)
const currentUpdateId = ref<number | undefined>(undefined)

const resetForm = () => {
  currentUpdateId.value = undefined
  addFormData.name = ""
  addFormData.type = "*"
  uploadRef.value?.clearFiles()
}
const fileList = ref<UploadUserFile[]>([])

const uploadTemplate = async () => {
  const formData = new FormData()
  if (fileList.value[0].raw) {
    formData.append("file", fileList.value[0].raw)
    const res = await uploadTemplateApi(formData)
    return res
  }
  return null
}

const handleCreate = () => {
  addFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      let res = null
      if (fileList.value[0] && fileList.value[0].raw) {
        res = await uploadTemplate()
      }
      if (currentUpdateId.value === undefined) {
        addFileDataApi({
          ...addFormData,
          fileTemplateFilename: res?.data.fileTemplateFilename,
          fileTemplateUrl: res?.data.fileTemplateUrl
        }).then(() => {
          showPromptMessage("success", "新增成功")
          addDialogVisible.value = false
          getFileData()
        })
      } else {
        updateFileDataApi({
          id: currentUpdateId.value,
          ...addFormData,
          fileTemplateFilename: res?.data.fileTemplateFilename,
          fileTemplateUrl: res?.data.fileTemplateUrl
        }).then(() => {
          showPromptMessage("success", "修改成功")
          addDialogVisible.value = false
          getFileData()
        })
      }
    } else {
      return false
    }
  })
}

interface Tree {
  [key: string]: any
}

const filterNode = (value: string, data: Tree) => {
  if (!value) return true
  return data.departmentName.includes(value)
}
watch(filterText, (val) => {
  treeRef.value!.filter(val)
})
const handleRefresh = () => {
  getFileData()
}

const props = {
  label: "departmentName",
  children: "children"
}

const updateData = ref<IUpdateGrantRequestData>({
  itemId: undefined,
  departmentIds: []
})
const treeRef = ref<InstanceType<typeof ElTree>>()
const defaultCheckedKeys = ref<number[]>([])
const treeDialogVisible = ref(false)
const TreeData = ref<IGetGrantListResponseData[]>([])
const handleAllocation = (row: IGetFileResponseData) => {
  loading.value = true
  updateData.value.itemId = row.id
  //获取权限
  getGrantListApi(row.id).then((res) => {
    TreeData.value = res.data.list
    defaultCheckedKeys.value = getCheckedKeys(res.data.list)
    treeDialogVisible.value = true
    loading.value = false
  })
}

const handleCheckChange = () => {
  updateData.value.departmentIds = treeRef.value!.getCheckedKeys(true) as number[]
}

const handleConfirmTree = () => {
  loading.value = true
  updateGrantApi(updateData.value)
    .then(() => {
      showPromptMessage("success", "更新成功")
      treeDialogVisible.value = false
    })
    .finally(() => {
      loading.value = false
    })
}

/** 覆盖默认上传行为 */
function requestUpload() {
  return new Promise(() => {})
}

/** 上传预处理 */
function beforeUpload() {}

const uploadRef = ref<UploadInstance | null>(null)
const handleExceed: UploadProps["onExceed"] = (files) => {
  uploadRef.value!.clearFiles()
  const file = files[0] as UploadRawFile
  file.uid = genFileId()
  uploadRef.value!.handleStart(file)
}
</script>

<style scoped lang="scss">
.tree-box::-webkit-scrollbar {
  width: 4px;
}
.tree-box::-webkit-scrollbar-thumb {
  background-color: #eee;
  border-radius: 4px;
}
:deep(.el-tree-node__expand-icon) {
  display: none;
}
</style>
